#include "characterabilitymodel.h"

#include <QStringList>
#include <QDebug>

CharacterAbilityModel::CharacterAbilityModel(QObject *parent) :
    QAbstractTableModel(parent)
{
    mdlHeaderData.append(tr("Ability"));
    mdlHeaderData.append(tr("Rank"));
    mdlHeaderData.append(tr("Pool"));
}

// QAbstractTableModel
int CharacterAbilityModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return abilities.count();
}

int CharacterAbilityModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return mdlHeaderData.count();
}

QVariant CharacterAbilityModel::data(const QModelIndex &index, int role) const
{
    AbilityItemModel* itm = abilities.at(index.row()).data();
    if ( role == Qt::DisplayRole )
        return itm->displayRole(index.column());
    else if ( role == Qt::EditRole )
        return itm->editRole(index.column());
    else if ( role == Qt::UserRole )
        return itm->userRole(index.column());
    else if ( role == Qt::FontRole )
        return itm->fontRole(index.column());
    return QVariant();
}

QVariant CharacterAbilityModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
            return QVariant();

    if (orientation == Qt::Horizontal)
    {
        return mdlHeaderData[section];
    }
    else
        return QString("%1").arg(section);
}

bool CharacterAbilityModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if ( role == Qt::EditRole )
    {
        QSharedPointer<AbilityItemModel> itm = abilities.at(index.row());
        int newValue = value.toInt();
        if ( index.column() == 1 ) // BUY RANK
        {
            double dcost = newValue - itm->abRank;
            if ( itm->isProfession )
                dcost /= 2;

            int cost = 0;
            if ( dcost > 0 )
                cost = static_cast<int>(dcost + 0.5);
            else if ( dcost < 0 )
                cost = static_cast<int>(dcost - 0.5);
            else
                cost = 0;

            if ( (itm->isInvestigation() && (chAvailableInvestigationPoints < cost)) ||
                    (!itm->isInvestigation() && chAvailableBuildPoints < cost) )
            {
                return false;
            }
            itm->abRank = value.toInt();
            //abilities.replace(index.row(), itm);
            //abilMap[itm.abName] = itm;
            if ( itm->isInvestigation() )
                emit investigationPointsSpent(cost);
            else
                emit buildPointsSpent(cost);
        }
        else if ( index.column() == 2 )
        {
            itm->abPool = value.toInt();
            //abilities.replace(index.row(), itm);
            //abilMap[itm.abName] = itm;
        }
        else
            return false;

        return true;
    }
    return false;
}

Qt::ItemFlags CharacterAbilityModel::flags(const QModelIndex &index) const
{
    if ( index.column() == 0 )
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    else
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
}

bool CharacterAbilityModel::addAbility(QString name, QString categ, int rank, int pool, bool occup)
{
    if ( abilMap.contains(name) )
        return false;

    beginInsertRows(QModelIndex(), abilities.count(), abilities.count());
    QSharedPointer<AbilityItemModel> itm(new AbilityItemModel(name, categ, rank, pool, occup));

    abilities.append(itm);
    abilMap.insert(name, itm);
    endInsertRows();

    return true;
}

bool CharacterAbilityModel::removeAt(QModelIndex idx)
{
    if ( !idx.isValid() )
        return false;
    if ( idx.row() >= abilities.count() )
        return false;

    beginRemoveRows(QModelIndex(), idx.row(), idx.row());
    QString name = abilities.at(idx.row())->abName;
    abilities.removeAt(idx.row());
    abilMap.remove(name);
    endRemoveRows();
    return true;
}

void CharacterAbilityModel::removeAll()
{
    beginRemoveRows(QModelIndex(), 0, abilities.count()-1);
    abilities.clear();
    abilMap.clear();
    endRemoveRows();
}

void CharacterAbilityModel::setAvailableBuildPoints(int value)
{
    chAvailableBuildPoints = value;
}

void CharacterAbilityModel::setAvailableInvestigationPoints(int value)
{
    chAvailableInvestigationPoints = value;
}

void CharacterAbilityModel::setOccupAbilities(QVariantList list)
{
    chOccupAbilities = list;
}

QString CharacterAbilityModel::getAbilityName(const QModelIndex & idx) const
{
    return abilities.at(idx.row())->abName;
}

int CharacterAbilityModel::getAbilityPool(const QModelIndex & idx) const
{
    return abilities.at(idx.row())->abPool;
}

int CharacterAbilityModel::getAbilityRank(const QModelIndex & idx) const
{
    return abilities.at(idx.row())->abRank;
}

bool CharacterAbilityModel::isProfessionSkill(const QModelIndex & idx) const
{
    return abilities.at(idx.row())->isProfession;
}

int CharacterAbilityModel::getAbilityRank(const QString & abName) const
{
    if (abilMap.contains(abName))
        return abilMap[abName]->abRank;
    return 0;
}

int CharacterAbilityModel::getAbilityPool(const QString & abName) const
{
    if (abilMap.contains(abName))
        return abilMap[abName]->abPool;
    return 0;
}

bool CharacterAbilityModel::isProfessionSkill(const QString & abName) const
{
    if (abilMap.contains(abName))
        return abilMap[abName]->isProfession;
    return false;
}

QVariantList CharacterAbilityModel::toVariantList()
{
    QVariantList list;
    foreach(QSharedPointer<AbilityItemModel> itm, abilities)
    {
        QVariantMap map;
        map.insert("name", itm->abName);
        map.insert("categ", itm->abCateg);
        map.insert("rank", itm->abRank);
        map.insert("pool", itm->abPool);
        map.insert("prof", itm->isProfession);

        list << map;
    }

    return list;
}

void CharacterAbilityModel::fromVariantList(QVariantList list)
{
    if ( list.isEmpty() )
        return;

    removeAll();

    beginInsertRows(QModelIndex(), 0, list.count()-1);
    foreach(QVariant qv, list)
    {
        QVariantMap map = qv.toMap();
        QSharedPointer<AbilityItemModel> itm( new AbilityItemModel(
                             map.value("name").toString(),
                             map.value("categ").toString(),
                             map.value("rank").toInt(),
                             map.value("pool").toInt(),
                             map.value("prof").toBool()) );
        abilities.append(itm);
        abilMap.insert(itm->abName, itm);
    }
    endInsertRows();

    qDebug() << "fromVariantList (3). RowCount: " << rowCount(QModelIndex());

    emit dataChanged(index(0, 0), index(abilities.count()-1, 0));
}

QStringList CharacterAbilityModel::abilityNames() const
{
    QStringList list;
    foreach(QSharedPointer<AbilityItemModel> itm, abilities)
        list << itm->abName;

    return list;
}

void CharacterAbilityModel::setAbilityRank(const QString & abName, int abRank)
{
    if ( abilMap.contains(abName) )
    {
        abilMap[abName]->abRank = abRank;
        int idxof = abilities.indexOf(abilMap[abName]);
        emit dataChanged(index(idxof-1, 0), index(idxof+1, 0));
    }
}


void CharacterAbilityModel::setAbilityPool(const QString & abName, int abPool)
{
    if ( abilMap.contains(abName) )
    {
        abilMap[abName]->abPool = abPool;
        int idxof = abilities.indexOf(abilMap[abName]);
        emit dataChanged(index(idxof-1, 0), index(idxof+1, 0));
    }
}

void CharacterAbilityModel::setProfessionSkill(const QString & abName, bool abFlag)
{
    if ( abilMap.contains(abName) )
    {
        abilMap[abName]->isProfession = abFlag;
        int idxof = abilities.indexOf(abilMap[abName]);
        emit dataChanged(index(idxof-1, 0), index(idxof+1, 0));
    }
}

void CharacterAbilityModel::setAbilityRank(const QModelIndex & idx, int abRank)
{
    if ( !idx.isValid() )
        return;

    abilities.at(idx.row())->abRank = abRank;
    emit dataChanged(index(idx.row()-1, 0), index(idx.row()+1, 0));
}


void CharacterAbilityModel::setAbilityPool(const QModelIndex & idx, int abPool)
{
    if ( !idx.isValid() )
        return;

    abilities.at(idx.row())->abPool = abPool;
    emit dataChanged(index(idx.row()-1, 0), index(idx.row()+1, 0));
}

void CharacterAbilityModel::setProfessionSkill(const QModelIndex & idx, bool abFlag)
{
    if ( !idx.isValid() )
        return;

    abilities.at(idx.row())->isProfession = abFlag;
    emit dataChanged(index(idx.row()-1, 0), index(idx.row()+1, 0));
}
